﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Diagnostics;
using System.IO;
 



namespace IMTApp
{

    /// <summary>
    /// Author: Elliott Perry 01/09/2011
    /// 
    /// This is the child class for SubmitEndorsement messages for Lime Street. It inherits from the base XMLMessage class.
    /// </summary>
    public class SubmitEndorsementMsg : XMLMessage
    {
        private XmlDocument _xml;
        private XmlDeclaration _xmlDec;
        private readonly MessageData _msg;
        GPM.QuickQuote.Logging.GpmLogger logger = new GPM.QuickQuote.Logging.GpmLogger();

        

        /// <summary>
        /// Main Constructor that is called from MainWindow.cs and passes the document for path for reading
        /// </summary>
        public SubmitEndorsementMsg(string docPath)
        {
            logger.LogInfo("DEBUG: Submit Endorsement MSG Object Created: Path = " + docPath + " at " + DateTime.Now.ToString("yyyy MM dd hh mm ss"));

            GlobalData.rootPath = @"C:\TSMSG\";

             //Create a MessageData Object;
            _msg = new MessageData();

            disectMessage(docPath);


        }

    
        /// <summary>
        /// TEST Constructor 
        /// </summary>
        public SubmitEndorsementMsg(string senderIdentification,
                                string AuthenticationToken,
                                string Operation,
                                string SourceEnvironment,
                                string BrokerID,
                                string BrokerContactName,
                                string BrokerContactTelephone,
                                string BrokerContactEmail,
                                string InsurerReinsurerName,
                                string UMR,
                                string Narrative,
                                string MasterType,
                                string ClassOfBusiness,
                                string CoverType,
                                string BrokerEndorsementReference,
                                string BrokerEndorsementName,
                                string AgreementPractice,
                                string VersionNumber,
                                string[,] PName, //Participants array
                                string[,] DocInfo
                                )
        {

            //Create a MessageData Object;
            _msg = new MessageData
                      {
                          SenderIdentification = senderIdentification,
                          AuthenticationToken = AuthenticationToken,
                          Operation = Operation,
                          SourceEnvironment = SourceEnvironment,
                          BrokerID = BrokerID,
                          BrokerContactName = BrokerContactName,
                          BrokerContactTelephone = BrokerContactTelephone,
                          BrokerContactEmail = BrokerContactEmail,
                          InsurerReinsurerName = InsurerReinsurerName,
                          UMR = UMR,
                          Narrative = Narrative,
                          MasterType = MasterType,
                          ClassOfBusiness = ClassOfBusiness,
                          CoverType = CoverType,
                          BrokerEndorsementReference = BrokerEndorsementReference,
                          BrokerEndorsementName = BrokerEndorsementName,
                          AgreementPractice = AgreementPractice,
                          VersionNumber = VersionNumber,
                          PName = PName,
                          DocInfo = DocInfo
                      };

            //Populate Data
            _msg.NumberOfDocuments = 1;


            //Begin to build the Lime-Street Formatted XML 
            buildXMLString(_msg);
           
        }
        

#region MakeXMLString


        /// <summary>
        /// This method builds the XML Message and places this into a string
        /// </summary>
        private void buildXMLString(MessageData Msg)
        {
            _xml = new XmlDocument();
            
            _xmlDec = _xml.CreateXmlDeclaration("1.0", null, null);

            XmlElement root = _xml.DocumentElement;
            _xml.InsertBefore(_xmlDec, root);

            XmlElement PackageEL = (XmlElement)_xml.AppendChild(_xml.CreateElement("Package"));

            PackageEL.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            //PackageEL.SetAttribute("noNamespaceSchemaLocation", "../Templates/EndorsementPackage_1_19_1.xsd");
            
            PackageEL.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");


            XmlElement SecurityEL = (XmlElement)PackageEL.AppendChild(_xml.CreateElement("Security"));

            XmlElement SenderIdentEL = (XmlElement)SecurityEL.AppendChild(_xml.CreateElement("SenderIdentification"));
            SenderIdentEL.InnerText = Msg.SenderIdentification;
            XmlElement AuthTokenEL = (XmlElement)SecurityEL.AppendChild(_xml.CreateElement("AuthenticationToken"));
            //AuthTokenEL.InnerText = Msg.AuthenticationToken;
            AuthTokenEL.InnerText = generateSecurityToken();

            XmlElement WorkFlowEL = (XmlElement)PackageEL.AppendChild(_xml.CreateElement("Workflow"));

            XmlElement OperationEL = (XmlElement)WorkFlowEL.AppendChild(_xml.CreateElement("Operation"));
            OperationEL.InnerText = Msg.Operation;

            XmlElement SourceEnvEL = (XmlElement)WorkFlowEL.AppendChild(_xml.CreateElement("SourceEnvironment"));
            SourceEnvEL.InnerText = Msg.SourceEnvironment;

            XmlElement EndorsementEL = (XmlElement)PackageEL.AppendChild(_xml.CreateElement("Endorsement"));

            XmlElement BrokerIDEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("BrokerId"));
            BrokerIDEL.InnerText = Msg.BrokerID;

            XmlElement BrokerContNameEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("BrokerContactName"));
            BrokerContNameEL.InnerText = Msg.BrokerContactName;

            XmlElement BrokerContTelEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("BrokerContactTelephone"));
            BrokerContTelEL.InnerText = Msg.BrokerContactTelephone;

            XmlElement BrokerContEmEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("BrokerContactEmail"));
            BrokerContEmEL.InnerText = Msg.BrokerContactEmail;

            //XmlElement InsurerReNameEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("InsurerReinsurerName"));
            XmlElement InsurerReNameEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("InsuredOrCedantName"));
            InsurerReNameEL.InnerText = Msg.InsurerReinsurerName;

            XmlElement UMREL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("UMR"));
            UMREL.InnerText = Msg.UMR;

            XmlElement NarrEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("Narrative"));
            NarrEL.InnerText = Msg.Narrative;

            XmlElement MasterTypeEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("MasterType"));
            MasterTypeEL.InnerText = Msg.MasterType;

            XmlElement CobEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("ClassOfBusiness"));
            CobEL.InnerText = Msg.ClassOfBusiness;

            XmlElement CoverTypeEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("CoverType"));
            CoverTypeEL.InnerText = Msg.CoverType;

            XmlElement BrokerEndRefEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("BrokerEndorsementReference"));
            BrokerEndRefEL.InnerText = Msg.BrokerEndorsementReference;

            XmlElement BrokerEndNameEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("BrokerEndorsementName"));
            BrokerEndNameEL.InnerText = Msg.BrokerEndorsementName;

            XmlElement AgreementPracticeEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("AgreementPractice"));
            AgreementPracticeEL.InnerText = Msg.AgreementPractice;

            XmlElement VersionNoEL = (XmlElement)EndorsementEL.AppendChild(_xml.CreateElement("VersionNumber"));
            VersionNoEL.InnerText = Msg.VersionNumber;

            XmlElement MarketEL = (XmlElement)PackageEL.AppendChild(_xml.CreateElement("Market"));

            logger.LogInfo("Number of Markets = " + Msg.getNumberOfMarkets());
            
            
            /////This loops around to insert the info for the underwriters.
            for (int i = 0; i < Msg.getNumberOfMarkets(); i++)
            {
                

                //create a Participant Element
                XmlElement ParticipantEL = (XmlElement)MarketEL.AppendChild(_xml.CreateElement("Participant"));

                //Create child elements. HACK, this is reading from Array, should really make Market Objects and keep them in list.
                XmlElement CarrierNameEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("CarrierName"));
                CarrierNameEL.InnerText = Msg.PName[i, 0];

                XmlElement CarrierConPerEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("CarrierContactPerson"));
                CarrierConPerEL.InnerText = Msg.PName[i, 1];

                XmlElement CarrierConEmailEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("CarrierContactEmail"));
                CarrierConEmailEL.InnerText = Msg.PName[i, 2];


                /////////TO-DO//////////
                //This element creates the agency for the market. Need validation in here for if the Agency is blank i.e PName[i,3] == Null
                XmlElement CarrierIdentEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("CarrierIdentification"));
                CarrierIdentEL.SetAttribute("agency", Msg.PName[i, 3]);
                CarrierIdentEL.InnerText = Msg.PName[i, 4];

                XmlElement CarrierIdentEL2 = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("CarrierIdentification"));
                CarrierIdentEL2.SetAttribute("agency", Msg.PName[i, 5]);
                CarrierIdentEL2.InnerText = Msg.PName[i, 6];

               

                XmlElement ContRefEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("ContractReference"));
                ContRefEL.InnerText = Msg.PName[i, 7];

                XmlElement PartFucnEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("ParticipantFunction"));
                PartFucnEL.InnerText = Msg.PName[i, 9];

                XmlElement DeliveryMethodEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("DeliveryMethod"));
                DeliveryMethodEL.InnerText = Msg.PName[i, 10];

                XmlElement HoldProcessingEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("HoldProcessing"));
                HoldProcessingEL.InnerText = Msg.PName[i, 11];

                XmlElement SequenceEL = (XmlElement)ParticipantEL.AppendChild(_xml.CreateElement("Sequence"));
                SequenceEL.InnerText = Msg.PName[i, 12];
                
                logger.LogInfo("DEBUG: Carrier " + i + "Complete");
            }
            

            XmlElement DocumentsEL = (XmlElement)PackageEL.AppendChild(_xml.CreateElement("Documents"));

            logger.LogInfo("DEBUG: Ready for Documents : " + Msg.NumberOfDocuments);

            ////This loops around to insert the info for the documents

            for (int i = 0; i < Msg.NumberOfDocuments; i++)
            {
                //create Document Element
                XmlElement DocumentEL = (XmlElement)DocumentsEL.AppendChild(_xml.CreateElement("Document"));

                //create child elements
                XmlElement FileReferenceEL = (XmlElement)DocumentEL.AppendChild(_xml.CreateElement("FileReference"));
                FileReferenceEL.InnerText = Msg.DocInfo[i,0];

                XmlElement FileNameEL = (XmlElement)DocumentEL.AppendChild(_xml.CreateElement("FileName"));
                FileNameEL.InnerText = Msg.DocInfo[i, 1];

                XmlElement DocumentTypeEL = (XmlElement)DocumentEL.AppendChild(_xml.CreateElement("DocumentType"));
                DocumentTypeEL.InnerText = Msg.DocInfo[i, 2];

                XmlElement DescriptionEL = (XmlElement)DocumentEL.AppendChild(_xml.CreateElement("Description"));
                DescriptionEL.InnerText = Msg.DocInfo[i, 3];

                XmlElement DocumentContentEL = (XmlElement)DocumentEL.AppendChild(_xml.CreateElement("DocumentContent"));
                //DocumentContentEL.InnerText = Msg.DocInfo[i, 4];
                DocumentContentEL.InnerText = convertDocumentToBase64(Msg.DocInfo[i, 4]);

                logger.LogInfo("DEBUG: Document " + i + " Complete");

            }

            logger.LogInfo("DEBUG: " + _xml.OuterXml.ToString());

            SaveXml(_xml.OuterXml.ToString());
        }


#endregion MakeXMLString


#region ReadInMessage
        /// <summary>
        /// This method should take the path from the constructor, break down the message and append it to the MessageData object
        /// </summary>
        private void disectMessage(string docPath)
        {
            //get delimiter from Global Data
            string delimiter = GlobalData.MessageDelimiter;
            List<string> data = new List<string>();
            
            //_msg.PName = new string[10,13];

            //Open up FileStream to Doc
            try
            {
                using (StreamReader reader = new StreamReader(docPath))
                {
                    //This string object
                    StringBuilder inputString = new System.Text.StringBuilder();
                    List<string> lstStartBody = new List<string>();
                    bool foundENDBODY = false;
                    int numOfMarkets = 1;
                    int numOfDocuments = 1;


                    //Read past the SUBMITENDORSEMENT,STARTBODY,
                    for (int i = 0; i < 28; i++)
                        reader.Read();


                    //This will read in the data for the STARTBODY area and put in a list
                    while (foundENDBODY == false)
                    {

                        //get the next Word i.e. until it finds a tab
                        while (reader.Peek() != GlobalData.MessageDelimiterASCII)
                        {
                            inputString.Append(char.ConvertFromUtf32(reader.Read()));
                        }

                        //check that it is not at end of body section and append to list
                        //logger.LogInfo("Comparing " + inputString.ToString() + " to ENDBODY");

                        if (inputString.ToString() == "ENDBODY")
                        {
                            logger.LogInfo("DEBUG: Found ENDBODY of Input Message. ");
                            foundENDBODY = true;
                            inputString.Clear();
                        }
                        else
                        {

                            //Put this into a list
                            lstStartBody.Add(inputString.ToString());

                            //logger.LogInfo("DATAFOUND: " + inputString.ToString());

                            //read the tab character
                            reader.Read();

                            //clear the inputString object
                            inputString.Clear();
                        }

                    }


                    //Now get Underwriter Information
                    logger.LogInfo("DEBUG: Getting Underwriter Information");

                    //Read past STARTMARKET,
                    for (int i = 0; i < 13; i++)
                        reader.Read();

                    //Get Number of Markets
                    while (reader.Peek() != GlobalData.MessageDelimiterASCII)
                    {
                        inputString.Append(char.ConvertFromUtf32(reader.Read()));
                    }


                    try
                    {
                        //Convert StringBuild into a String
                        string Nom = inputString.ToString();

                        //Convert String into a Int
                        numOfMarkets = Convert.ToInt16(Nom);

                        logger.LogInfo("DEBUG: Number Of Markets = " + numOfMarkets);
                    }
                    catch (Exception e)
                    {
                        logger.LogInfo("ERROR: Error determining number of markets :" + inputString + " :" + e);

                    }

                    //clear the input string
                    inputString.Clear();

                    //move over the comma
                    reader.Read();

                    //create the correct size array
                    string[,] UnderwriterArray = new string[numOfMarkets, 13];

                    //for the number of markets that there are
                    for (int i = 0; i < numOfMarkets; i++)
                    {
                        //for the number of properties per Underwriter
                        //HACK: This should be read from GLOBAL DATA
                        
                        for (int j = 0; j < 13; j++)
                        {
                            //read the next input up to the delimiter and put in List.
                            while (reader.Peek() != GlobalData.MessageDelimiterASCII)
                            {
                                //read in the data from the stream.
                                inputString.Append(char.ConvertFromUtf32(reader.Read()));

                            }
                             
                                logger.LogInfo("DEBUG: Saving " + inputString.ToString() + " to UW Array Position[" + i + "," + j + "]");

                                //append to array
                                UnderwriterArray[i, j] = inputString.ToString();

                                //clear the input string
                               inputString.Clear();
                            

                                //move over the Comma 
                                reader.Read();
                        }
                    }


                    //clear the input string
                    inputString.Clear();

                     //Now get Underwriter Information
                    logger.LogInfo("DEBUG: Getting Document Information");

                    // Read over ENDMARKET & STARTDOCS, 19 Characters
                    for (int i = 0; i < 20; i++)
                        reader.Read();

                    //clear the input string
                    inputString.Clear();

                    
                  
                    //Get Number of Documents
                    while (reader.Peek() != GlobalData.MessageDelimiterASCII)
                    {
                                               
                        inputString.Append(char.ConvertFromUtf32(reader.Read()));
                    }

                     try
                    {
                        //Convert StringBuild into a String
                        string Nod = inputString.ToString();

                        //Convert String into a Int

                        numOfDocuments = Convert.ToInt16(Nod);
                        _msg.NumberOfDocuments = numOfDocuments;

                        logger.LogInfo("DEBUG: Number Of Documents = " + numOfDocuments);
                    }
                    catch (Exception e)
                    {
                        logger.LogInfo("ERROR: Error determining number of documents : '" + inputString + "' :" + e);

                    }

                    //clear the input string
                    inputString.Clear();

                    //move over the comma
                    reader.Read();

                    //create the correct size array
                    string[,] DocumentArray = new string[numOfMarkets, 5];

                    //For the number of documents that there are
                    for (int i = 0; i < numOfDocuments; i++)
                    {
                        //for the number of parameters associated with documents
                        //HACK: this should be read from GlobalData
                        for (int j = 0; j < 5; j++)
                        {

                            //read the next input upto the delimiter and put in List.
                            while (reader.Peek() != GlobalData.MessageDelimiterASCII)
                            {
                                //read in the data from the stream.
                                inputString.Append(char.ConvertFromUtf32(reader.Read()));

                            }

                            logger.LogInfo("DEBUG: Saving " + inputString.ToString() + " to Doc Array Position[" + i + "," + j + "]");

                            //append to array
                            DocumentArray[i, j] = inputString.ToString();

                            //clear the input string
                            inputString.Clear();


                            //move over the Comma 
                            reader.Read();

                        }

                    }
                    
                   
                    //Append this data into the MessageData object;
                    logger.LogInfo("DEBUG: Now appending data to MSG Object");

                    _msg.SenderIdentification = lstStartBody[0];
                    _msg.AuthenticationToken = lstStartBody[1];
                    _msg.Operation = lstStartBody[2];
                    _msg.SourceEnvironment = lstStartBody[3];
                    _msg.BrokerID = lstStartBody[4];
                    _msg.BrokerContactName = lstStartBody[5];
                    _msg.BrokerContactTelephone = lstStartBody[6];
                    _msg.BrokerContactEmail = lstStartBody[7];
                    _msg.InsurerReinsurerName = lstStartBody[8];
                    _msg.UMR = lstStartBody[9];
                    _msg.Narrative = lstStartBody[10];
                    _msg.MasterType = lstStartBody[11];
                    _msg.ClassOfBusiness = lstStartBody[12];
                    _msg.CoverType = lstStartBody[13];
                    _msg.BrokerEndorsementReference = lstStartBody[14];
                    _msg.BrokerEndorsementName = lstStartBody[15];
                    _msg.AgreementPractice = lstStartBody[16];
                    _msg.VersionNumber = lstStartBody[17];
                    _msg.PName = UnderwriterArray;
                    _msg.DocInfo = DocumentArray; 

                    logger.LogInfo("... completed");

                   
                    //cleanup
                    reader.Close();
                    reader.Dispose();
                    

                    //Begin to build the Lime-Street Formatted XML 
                    buildXMLString(_msg);


                }
                //end streamreader
            }
            catch (Exception e)
            {
                logger.LogInfo("ERROR: Error Opening File in disectMessage: " + e);
                
            }

            
            

        }
#endregion ReadInMessage



        /// <summary>
        /// This method will take the document objects, called the convertTo64 method and insert them into the correct part of the message
        /// </summary>
        public void insertDocuments()
        {

        }

    }
}
